"use strict";
// function demo(x:number,y:number):number{
//     return x + y + 'xyz'
// }
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
// let result = demo(1,2)
// console.log(result);
// let str1: string // TS官方推荐的写法
// str1 = new String('123')  // 报错 不能将'String' 分配给类型'string'
// let str2: String
let a; // a为未知类型 不知道后面的人会如何用它 unknown
a = 99;
a = false;
a = 'hello';
console.log('a', a);
let x;
// x = a 这会直接报错 因为它不知道a到底是啥
// 应该这样-方式1  --typeof
// if(typeof a ==='string'){
//     x = a
// }
// 方式--2 --断言
// x = a as string
// 方式3 泛型
x = a;
// never
let a1; // a1这辈子都不能翻身了
// a1 = 9
// never 函数说白了它里面就是不能结束，不能正常结束
// 限制函数的返回值---是及其特殊的函数或者死循环的函数
// function demo():never{
// throw new Error('程序运行异常')  //--到这里会结束函数的调用
// return 666
// }
// function demo():never{
//     demo() // 死循环
// }
// let x1 = demo()
// console.log(x1);
// 这里是never主动推断出来的
let a3;
a3 = 'hello';
// a3 = 9
if (typeof a3 === 'string') {
    console.log(a3.toUpperCase());
}
else {
    console.log(a3); // 没有任何值能走到第七行
}
// void
function logMessage(msg) {
    console.log(msg);
}
logMessage('你好');
let a4; //
let b;
a = {};
a = { name: 'tom' };
a = [1, 3, 5, 7, 9];
a = function () { };
class Person {
}
a = new Person();
// 索引签名
let person;
// 后面可以无限加
person = { name: 'tom', age: 18, gender: '男', city: '北京' };
// 函数类型
// 箭头函数右边限制的是 返回值
// TypeScript 中的 => 在函数类型声明时表示==函数类型,==描述其==参数类型==和返回类型。
let count2;
count2 = function (a, b) {
    return a + b;
};
// 定义数组类型--方式1
let arr;
// 方式2
let arr2;
arr = ['a', 'b'];
arr2 = [1, 2, 3, 4];
// 枚举--默认自增
// enum Direction {
//     Up,
//     Down,
//     Left,
//     Right
// }
var Direction;
(function (Direction) {
    Direction[Direction["Up"] = 5] = "Up";
    Direction[Direction["Down"] = 12] = "Down";
    Direction[Direction["Left"] = 13] = "Left";
    Direction[Direction["Right"] = 14] = "Right";
})(Direction || (Direction = {}));
console.log('Direction', Direction);
function walk(data) {
    // console.log('data',data);
    // console.log('Direction.Up',Direction.Up);   // 0
    // #region
    // #endregion
    if (data === Direction.Up) {
        console.log("向上");
    }
    else if (data === Direction.Down) {
        console.log("向下");
    }
    else if (data === Direction.Left) {
        console.log("向左");
    }
    else if (data === Direction.Right) {
        console.log("向右");
    }
}
// walk('up')  原来这就是枚举的作用--因为这个不行
walk(Direction.Down); // 这个可以
console.log(0 /* Direction2.Up */);
let price;
price = 100;
function printstatus(status) {
    console.log(status);
}
printstatus(404);
printstatus('200');
printstatus('501');
function logGender(str) {
    console.log(str);
}
logGender('男');
logGender('女');
const house = {
    height: 100,
    width: 100,
    num: 3,
    cell: 4,
    room: '702'
};
// LogFunc = 999
const f1 = () => {
    // 不写或者 return undefined 都不报错
    // return undefined
};
// 没有学type之前的写法是这样的
function LogFunc() {
}
// f2 和 f3是一样的意思
const f2 = () => 666;
const f3 = () => { return 666; };
// 为啥ts在这里不会严格要求函数
// 类
class Person2 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    speak() {
        console.log(`我叫:${this.name},今年${this.age}岁`);
    }
}
class Student extends Person2 {
    constructor(name, age, grade) {
        super(name, age);
        this.grade = grade;
    }
    study() {
        console.log(`${this.name}正在努力学习中.......`); // 这就是类的内部
    }
    speak() {
        console.log(`我是学生,我叫:${this.name},今年${this.age}岁`);
    }
}
const s1 = new Student('李同学', 16, '三年级');
console.log(s1.study(), s1.speak());
// 简写前
class Person3 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}
// 简写后
// class Person4 {
//     constructor(
//         public name: string,
//         public age: number){
//     }
// }
class Person4 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
        // 谁调用就指向谁
        console.log('this', this); // Person4 {name: 'tom', age: 18},Student2 {name: 'tom2', age: 12}
    }
    getDetails() {
        return `我叫1111: ${this.name},年龄是:${this.age}`;
    }
    introduce() {
        console.log(this.getDetails());
    }
}
let p2 = new Person4('tom', 18);
// p2.age
// p2.name
// p2.getDetails
// 加了protected，引用这些属性就会报错
p2.introduce();
class Student2 extends Person4 {
    // 这里写不写都可以
    // constructor(name:string,age:number){
    //     super(name,age)
    // }
    study() {
        this.getDetails();
        console.log(`${this.name}正在努力学习`);
    }
}
const s2 = new Student2('tom2', 12);
s2.study();
// 抽象类
class Package {
    // 构造方法
    constructor(weight) {
        this.weight = weight;
    }
    // 具体方法
    printPackage() {
        console.log(`包裹重量为:${this.weight}kg,运费为:${this.calculate()}元`);
    }
    sayHello() { }
}
// const p1 = new Package(100)
class StandardPackage extends Package {
    constructor(weight, unitPrice) {
        super(weight); // 调用父类的构造函数，
        this.unitPrice = unitPrice;
        super.sayHello(); // 调用父类的方法
    }
    calculate() {
        return this.weight * this.unitPrice;
    }
}
const s4 = new StandardPackage(10, 5);
s4.printPackage();
// 定义一个类Person，实现 PersonInterface 接口
class Person5 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    speak(n) {
        for (let i = 0; i < n; i++) {
            console.log(`你好，我叫${this.name}，我的年龄是${this.age}`);
        }
    }
}
const p1 = new Person5('tom', 18);
p1.speak(3);
const user = {
    name: '张三',
    gender: '男',
    age: 28,
    run(n) {
        console.log(`奔跑了${n}米`);
    }
};
const count = (x, y) => {
    return x + y;
};
const stu2 = {
    name: '张三',
    age: 18,
    grade: '三年级',
    // time:'' 报错
};
// type PersonType =  {
//     name: string;
//     age: number;
//     speak(): void
// }
let p6 = {
    name: 'tom',
    age: 18,
    speak() {
        console.log(this.name);
    }
};
const student2 = {
    name: '山东黄金',
    age: 18,
    grade: '但是',
    speak: () => { }
};
// 相同点
// 不同点
// 泛型
// function logData<T>(data:T){
//     console.log(data);
// }
// logData<number>(100)
function logData(data1, data2) {
    return Date.now() % 2 ? console.log(data1) : console.log(data2);
}
logData(100, true);
logData('100', 963);
let p7 = {
    name: 'tom',
    age: 18,
    extraInfo: 250
};
let p = {
    name: '凯杰',
    age: 18,
    extraInfo: {
        title: '高级工程师',
        company: '发发发科技有限公司'
    }
};
// 泛型类
class Person6 {
    constructor(name, age, extraInfo) {
        this.name = name;
        this.age = age;
        this.extraInfo = extraInfo;
    }
    speak() {
        console.log(`我叫${this.name}今年${this.age}岁`);
        console.log(this.extraInfo);
    }
}
// const p8 = new Person6<number>('你好',18,60)
const p8 = new Person6('你好', 18, { title: 'hehe', company: '147' });
// 类型声明文件.d.ts
// import {add,mul} from './demo.js'
// console.log(add(1,2))
// console.log(mul(3,4))
// 类型文件的主要作用是为现有的js代码提供类型信息，
// 使得ts能够在使用这些js库或者模块时，进行类型检查和提示
/*
Demo函数会在Person类定义时执行
参数说明：
    ○ target参数是被装饰的类，即：Person
*/
// 装饰器
function Demo2(target) {
    console.log('target', target);
}
let Person7 = class Person7 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
};
Person7 = __decorate([
    Demo2
], Person7);
function CustomString(target) {
    target.prototype.toString = function () {
        console.log('this', this); // 实例P9
        return JSON.stringify(this); // 这里不要填target
    };
    // Object.seal(target.prototype)
}
let Person8 = class Person8 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
};
Person8 = __decorate([
    CustomString
], Person8);
const p9 = new Person8('张三', 20);
console.log(p9.toString());
// @ts-ignore  这是忽略检查的意思
Person8.prototype.x = 99;
console.log(p9.x);
// **类装饰器有返回值**：若类装饰器返回一个新的类，那这个新类将**替换**掉被装饰的类。
// **类装饰器无返回值**：若类装饰器无返回值或返回`undefined`，那被装饰的类**不会**被替换。
function Demo3(target) {
    return class {
        test() {
            console.log(200);
            console.log(300);
            console.log(400);
        }
    };
}
let Person9 = class Person9 {
    test() {
        console.log(100);
    }
};
Person9 = __decorate([
    Demo3 // 装饰 Person9
], Person9);
console.log('Person9', Person9);
function LogTime(target) {
    return class extends target {
        constructor(...args) {
            super(...args);
            this.createdTime = new Date();
        }
        getTime() {
            return `该对象的创建时间是:${this.createdTime}`;
        }
    };
}
/*
@LogTime
class Person10 {
上面这一段等价于 LogTime(Person10)
*/
let Person10 = class Person10 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    speak() {
        console.log('你好呀');
    }
};
Person10 = __decorate([
    LogTime
], Person10);
const p10 = new Person10('张三', 19);
console.log('p10', p10);
console.log(p10.getTime());
// 类Person11的简写形式
class Person11 {
    // name: string
    // age:number
    // constructor(name:string,age:number){
    //     this.name = name
    //     this.age = age
    // }
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}
function LogInfo2(n) {
    // 下面的是装饰器
    return function (target) {
        target.prototype.introduce = function () {
            for (let i = 0; i < n; i++) {
                console.log(`我的名字:${this.name},我的年龄:${this.age}岁`);
            }
        };
    };
}
let Person12 = class Person12 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    speak() {
        console.log('你好呀');
    }
};
Person12 = __decorate([
    LogInfo2(3)
], Person12);
const p12 = new Person12('刘惠杰', 18);
p12.introduce();
/*
参数说明：
    ○ target: 对于静态属性来说值是类，对于实例属性来说值是类的原型对象。
    ○ propertyKey: 属性名。
*/
// 属性装饰器
function Demo(target, propertykey) {
    console.log(target, propertykey); // target-{}--(就是Person13), propertykey--name
}
class Person13 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}
__decorate([
    Demo
], Person13.prototype, "name", void 0);
__decorate([
    Demo
], Person13.prototype, "age", void 0);
// 给指定对象添加属性用的
let value = 130;
Object.defineProperty(Person13.prototype, 'age', {
    get() {
        return value;
    },
    set(val) {
        value = val;
    },
});
const p13 = new Person13('你好', 17);
console.log(p13);
// 方法装饰器
function Demo5(target, propertyKey, description) {
    console.log(target);
    console.log(propertyKey);
    console.log(description);
}
class Person14 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    speak() {
        console.log(`你好我的名字:${this.name},今年${this.age}岁`);
    }
    static isAdult(age) {
        return age >= 18;
    }
}
__decorate([
    Demo5 // 放在谁上面就装饰谁
], Person14.prototype, "speak", null);
